﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperKit {
    public class PageSpliterPage {
        public int Index { get; }
        public List<FileInfo> Files { get; }
        public int Count => Files.Count;
        public PageSpliterPage(int index, int count) {
            Index = index;
            Files = new List<FileInfo>(count);
        }
        public PageSpliterPage(int index, List<FileInfo> files) {
            Index = index;
            Files = files;
        }
    }

    public class PageSpliter {
        public DirectoryInfo Dir { get; }
        public int PageCount { get; }
        public int AvgCount { get; private set; }
        public int RequireCount { get; }
        public string[] Exts { get; }
        public List<FileInfo> AllFiles { get; private set; }
        public PageSpliterPage[] Pages { get; private set; }
        public int Page { get; private set; }


        public PageSpliter(string dir, int pageCount, int requireCount, string[] ext) {
            this.Dir = new DirectoryInfo(dir);
            this.PageCount = pageCount;
            this.RequireCount = requireCount == 0 ? pageCount : requireCount;
            this.Exts = ext;
            Split();
        }

        public bool IsOnePage => PageCount == 0 || RequireCount == 0 || AllFiles.Count < RequireCount;

        private void Split() {
            AllFiles = new List<FileInfo>();
            int count = DirectoryEx.GetAllFiles(Dir, AllFiles, Exts);
            if (IsOnePage) {
                FillOnePage();
                return;
            }

            Page = (int)Math.Ceiling(count / (double)PageCount);
            AvgCount = (int)Math.Ceiling(count / (double)Page);

            FillPage();
        }

        private void FillPage() {
            Pages = new PageSpliterPage[Page];
            int start = 0;
            for (int i = 0; i < Page; i++) {
                Pages[i] = new PageSpliterPage(i, AvgCount);
                FillPage(Pages[i], start);
                start += AvgCount;
            }
        }

        private void FillPage(PageSpliterPage p, int start) {
            for (int i = 0; i < AvgCount; i++) {
                var f = SafeGet(AllFiles, i + start);
                if (f != null) {
                    p.Files.Add(f);
                }                
            }
        }

        private T SafeGet<T>(List<T> list, int index) {
            if (list == null || list.Count == 0) return default(T);
            if (index < 0 || index >= list.Count) return default(T);
            return list[index];
        }

        private void FillOnePage() {
            Pages = new PageSpliterPage[1];
            Pages[0] = new PageSpliterPage(0, AllFiles);
            Page = 1;
        }
    }
}
